<template>
  <el-form
      ref="formRef"
      :model="formData"
      :rules="rules"
      :label-width="labelWidth"
  >
    <el-row :gutter="20">
      <el-col v-for="item in formItems" :key="item.field_key" :span="24" :class="{ more: item.supported_operator === 'more' }">
        <el-form-item
            :label="item.field_label"
        >

          <div v-if="Object.keys(item.supported_operator_options).length > 1" :class="{ invalid: !item.supported_operator && item.is_require === 'yes' }" style="margin-right: 10px;">
            <el-select v-model="item.supported_operator" style="width: 140px;" @change="onOperatorChange($event, item)">
              <el-option
                  v-for="key in Object.keys(item.supported_operator_options || {})"
                  :key="item.supported_operator_options[key]"
                  :label="key"
                  :value="item.supported_operator_options[key]"
              />
            </el-select>
          </div>

          <div v-if="item.supported_operator === 'more'" class="more-condition">
            <div v-if="moreLoading" style="color: #999;">加载中...</div>

            <div v-else v-for="(moreItem, index) in item.more_condition" :key="index">
              <div style="display: inline;margin-right: 10px;" :class="{ invalid: !moreItem.field_key && item.is_require === 'yes' }" >
                <el-select v-model="moreItem.field_key" style="width: 140px;" @change="onMoreFieldChange($event, item, moreItem)">
                  <el-option
                      v-for="option in item.moreOptions"
                      :key="option.field_key"
                      :label="option.field_label"
                      :value="option.field_key"
                  />
                </el-select>
              </div>

              <div style="display: inline;" :class="{ invalid: !moreItem.supported_operator && item.is_require === 'yes' }">
                <el-select v-model="moreItem.supported_operator" :disabled="!moreItem.field_key" :placeholder="moreItem.placeholder" style="width: 140px;margin-right: 10px;" @change="onMoreOperatorChange($event, moreItem)">
                  <el-option
                      v-for="option in moreItem.options"
                      :key="option.value"
                      :label="option.text"
                      :value="option.value"
                  />
                </el-select>
              </div>

              <template v-if="moreItem.field_component === 'number'">
                <template v-if="['between', 'not_between'].includes(moreItem.supported_operator)">
                  <el-input-number v-model="moreItem.field_value[0]" :max="moreItem.field_value[1] - 1" :controls="false" :placeholder="moreItem.placeholder" :class="{ invalid: (!moreItem.field_value[0] || moreItem.field_value[0] === 0 && item.is_require === 'yes') }" style="width: 140px;margin-right: 5px;">
                    <template v-if="moreItem.pre_append_text" #prefix>
                      {{ moreItem.pre_append_text }}
                    </template>
                    <template v-if="moreItem.end_append_text" #suffix>
                      {{ moreItem.end_append_text }}
                    </template>
                  </el-input-number>
                  <span style="width: 14px;display: inline-block;text-align: center;margin-right: 5px;">-</span>
                  <el-input-number v-model="moreItem.field_value[1]" :min="moreItem.field_value[0] + 1" :controls="false" :placeholder="moreItem.placeholder" :class="{ invalid: !moreItem.field_value[1] && item.is_require === 'yes' }" style="width: 140px;margin-right: 10px;">
                    <template v-if="moreItem.pre_append_text" #prefix>
                      {{ moreItem.pre_append_text }}
                    </template>
                    <template v-if="moreItem.end_append_text" #suffix>
                      {{ moreItem.end_append_text }}
                    </template>
                  </el-input-number>
                </template>
                <el-input-number v-else v-model="moreItem.field_value" :controls="false" :placeholder="moreItem.placeholder" :class="{ invalid: !moreItem.field_value || moreItem.field_value === 0 }" style="width: 140px;margin-right: 10px;">
                  <template v-if="moreItem.pre_append_text" #prefix>
                    {{ moreItem.pre_append_text }}
                  </template>
                  <template v-if="moreItem.end_append_text" #suffix>
                    {{ moreItem.end_append_text }}
                  </template>
                </el-input-number>
              </template>
              <template v-else-if="moreItem.field_component === 'input'">
                <template v-if="['one_of'].includes(moreItem.supported_operator)">
                  <el-input-tag v-model="moreItem.field_value" :placeholder="placeholder" :class="{ invalid: moreItem.field_value.length === 0 && item.is_require === 'yes' }" style="width: 200px;margin-right: 10px;">
                    <template v-if="moreItem.pre_append_text" #prefix>
                      {{ moreItem.pre_append_text }}
                    </template>
                    <template v-if="moreItem.end_append_text" #suffix>
                      {{ moreItem.end_append_text }}
                    </template>
                  </el-input-tag>
                </template>
                <template v-else-if="['empty', 'not_empty'].includes(moreItem.supported_operator)">
                  <el-input v-model="moreItem.field_value" :placeholder="moreItem.placeholder" style="width: 120px;margin-right: 10px;">
                    <template v-if="moreItem.pre_append_text" #prefix>
                      {{ moreItem.pre_append_text }}
                    </template>
                    <template v-if="moreItem.end_append_text" #suffix>
                      {{ moreItem.end_append_text }}
                    </template>
                  </el-input>
                </template>
                <el-input v-else v-model="moreItem.field_value" :class="{ invalid: !moreItem.field_value && item.is_require === 'yes' }" style="width: 140px;margin-right: 10px;">
                  <template v-if="moreItem.pre_append_text" #prefix>
                    {{ moreItem.pre_append_text }}
                  </template>
                  <template v-if="moreItem.end_append_text" #suffix>
                    {{ moreItem.end_append_text }}
                  </template>
                </el-input>
              </template>
              <template v-else-if="moreItem.field_component === 'select'">
                <el-select v-model="moreItem.field_value" :multiple="['one_of'].includes(moreItem.supported_operator)" :placeholder="moreItem.placeholder" :class="{ invalid: (['one_of'].includes(moreItem.supported_operator) ? moreItem.field_value.length === 0 : !moreItem.field_value) && item.is_require === 'yes' }" style="width: 140px;margin-right: 10px;">
                  <template v-if="moreItem.pre_append_text" #prefix>
                    {{ moreItem.pre_append_text }}
                  </template>
                  <el-option
                      v-for="option in moreItem['extra_config'].options"
                      :key="option.value"
                      :label="option.label"
                      :value="option.value"
                  ></el-option>
                </el-select>
              </template>
              <template v-else-if="moreItem.field_component === 'textarea'">
                <el-input v-model="moreItem.field_value" type="textarea" :placeholder="moreItem.placeholder" :class="{ invalid: (['empty', 'not_empty'].includes(moreItem.supported_operator) ? false : !moreItem.field_value) && item.is_require === 'yes' }" style="width: 200px;margin-right: 10px;" />
              </template>
              <template v-else-if="moreItem.field_component === 'date'">
                <div v-if="['between', 'not_between'].includes(moreItem.supported_operator)" :class="{ invalid: (!moreItem.field_value || moreItem.field_value.length === 0) && item.is_require === 'yes' }" style="margin-right: 10px;">
                  <el-date-picker
                      v-model="moreItem.field_value"
                      type="daterange"
                      value-format="YYYY-MM-DD"
                      :clearable="false"
                      :start-placeholder="moreItem.placeholder"
                      :end-placeholder="moreItem.placeholder"
                      style="width: 240px;"
                  />
                </div>
                <div v-else :class="{ invalid: !moreItem.field_value }" style="margin-right: 10px;">
                  <el-date-picker
                      v-model="moreItem.field_value"
                      type="date"
                      value-format="YYYY-MM-DD"
                      :clearable="false"
                      :placeholder="moreItem.placeholder"
                      style="width: 200px;"
                  />
                </div>
              </template>
              <template v-else-if="moreItem.field_component === 'datetime'">
                <div v-if="['between', 'not_between'].includes(moreItem.supported_operator)" :class="{ invalid: (!moreItem.field_value || moreItem.field_value.length === 0) && item.is_require === 'yes' }" style="margin-right: 10px;">
                  <el-date-picker
                      v-model="moreItem.field_value"
                      type="datetimerange"
                      value-format="YYYY-MM-DD HH:mm:ss"
                      :clearable="false"
                      :start-placeholder="moreItem.placeholder"
                      :end-placeholder="moreItem.placeholder"
                      style="width: 380px;"
                  />
                </div>
                <div v-else :class="{ invalid: !moreItem.field_value }" style="margin-right: 10px;">
                  <el-date-picker
                      v-model="moreItem.field_value"
                      type="datetime"
                      value-format="YYYY-MM-DD HH:mm:ss"
                      :clearable="false"
                      :placeholder="moreItem.placeholder"
                      style="width: 200px;"
                  />
                </div>
              </template>
              <template v-else-if="moreItem.field_component === 'time'">
                <div v-if="['between', 'not_between'].includes(moreItem.supported_operator)" :class="{ invalid: (!moreItem.field_value || moreItem.field_value.length === 0) && item.is_require === 'yes' }" style="margin-right: 10px;">
                  <el-time-picker
                      is-range
                      v-model="moreItem.field_value"
                      :clearable="false"
                      :start-placeholder="moreItem.placeholder"
                      :end-placeholder="moreItem.placeholder"
                      style="width: 200px;"
                  />
                </div>
                <div v-else :class="{ invalid: !moreItem.field_value }" style="margin-right: 10px;">
                  <el-time-picker
                      v-model="moreItem.field_value"
                      :clearable="false"
                      :placeholder="moreItem.placeholder"
                      style="width: 200px;"
                  />
                </div>
              </template>

              <div style="display: inline;" :class="{ invalid: !moreItem.value && item.is_require === 'yes' }">

                <el-input-number
                    v-if="item.field_component === 'number'"
                    v-model="moreItem.value"
                    :controls="false"
                    :placeholder="item.placeholder"
                    style="width: 140px;margin-right: 10px;"
                >
                  <template v-if="item.pre_append_text" #prefix>
                    {{ item.pre_append_text }}
                  </template>
                  <template v-if="item.end_append_text" #suffix>
                    {{ item.end_append_text }}
                  </template>
                </el-input-number>

                <el-input
                    v-else-if="item.field_component === 'input'"
                    v-model="moreItem.value"
                    :placeholder="item.placeholder"
                    style="width: 140px;margin-right: 10px;"
                >
                  <template v-if="item.pre_append_text" #prefix>
                    {{ item.pre_append_text }}
                  </template>
                  <template v-if="item.end_append_text" #suffix>
                    {{ item.end_append_text }}
                  </template>
                </el-input>

                <el-select
                    v-else-if="item.field_component === 'select'"
                    v-model="moreItem.value"
                    :placeholder="item.placeholder"
                    style="width: 140px;margin-right: 10px;"
                >
                  <template v-if="item.pre_append_text" #prefix>
                    {{ item.pre_append_text }}
                  </template>
                  <el-option
                      v-for="key in Object.keys(item.options)"
                      :key="item.options[key]"
                      :label="key"
                      :value="item.options[key]"
                  />
                </el-select>
              </div>

              <div>
                <el-icon v-if="item.more_condition.length > 1" :size="15" style="margin-right: 15px;vertical-align: middle;cursor: pointer;" @click="() => item.more_condition.splice(index, 1)">
                  <Close color="var(--el-color-danger)" />
                </el-icon>
                <el-icon :size="15" style="margin-right: 10px;vertical-align: middle;cursor: pointer;" @click="addCondition(item, index)">
                  <Plus color="var(--el-color-primary)" />
                </el-icon>
              </div>
            </div>

          </div>

          <div v-else-if="item.supported_operator === 'equal'" :class="{ invalid: !item.value && item.is_require === 'yes' }">

            <el-input
                v-if="item.field_component === 'input'"
                v-model="item.value"
                :placeholder="item.placeholder"
                style="width: 140px;margin-right: 10px;"
            >
              <template v-if="item.pre_append_text" #prefix>
                {{ item.pre_append_text }}
              </template>
              <template v-if="item.end_append_text" #suffix>
                {{ item.end_append_text }}
              </template>
            </el-input>

            <el-input-number
                v-if="item.field_component === 'number'"
                v-model="item.value"
                :controls="false"
                :placeholder="item.placeholder"
                align="left"
                style="width: 140px;margin-right: 10px;"
            >
              <template v-if="item.pre_append_text" #prefix>
                {{ item.pre_append_text }}
              </template>
              <template v-if="item.end_append_text" #suffix>
                {{ item.end_append_text }}
              </template>
            </el-input-number>

            <template v-else-if="item.field_component === 'select'">
              <div v-if="loading" style="color: #999;">加载中...</div>

              <el-select
                  v-else
                  v-model="item.value"
                  :placeholder="item.placeholder"
                  style="width: 140px;margin-right: 10px;"
              >
                <el-option
                    v-for="{text, value} in item.options"
                    :key="value"
                    :label="text"
                    :value="value"
                />
              </el-select>
            </template>
          </div>

          <div v-else-if="item.supported_operator === 'between'" :class="{ invalid: item.value.some((v) => !v) && item.is_require === 'yes' }" style="display: inline-flex
;">
            <el-input-number v-model="item.value[0]" :max="item.value[1] - 1" :controls="false" :placeholder="item.placeholder" :class="{ invalid: item.value[0] === undefined }" style="width: 140px;margin-right: 10px;">
              <template v-if="item.pre_append_text" #prefix>
                {{ item.pre_append_text }}
              </template>
              <template v-if="item.end_append_text" #suffix>
                {{ item.end_append_text }}
              </template>
            </el-input-number>
            <span style="width: 14px;display: inline-block;text-align: center;">-</span>
            <el-input-number v-model="item.value[1]" :min="item.value[0] + 1" :controls="false" :placeholder="item.placeholder" :class="{ invalid: item.value[1] === undefined }" style="width: 140px;">
              <template v-if="item.pre_append_text" #prefix>
                {{ item.pre_append_text }}
              </template>
              <template v-if="item.end_append_text" #suffix>
                {{ item.end_append_text }}
              </template>
            </el-input-number>
          </div>

          <div v-else-if="item.supported_operator === 'one_of'" :class="{ invalid: item.value?.length === 0 && item.is_require === 'yes' }">
            <div v-if="loading" style="color: #999;">加载中...</div>

            <el-select
                v-else
                v-model="item.value"
                multiple
                :placeholder="item.placeholder"
                style="width: 240px;margin-right: 10px;"
            >
              <el-option
                  v-for="{text, value} in item.options"
                  :key="value"
                  :label="text"
                  :value="value"
              />
            </el-select>
          </div>

        </el-form-item>
      </el-col>
    </el-row>
  </el-form>
</template>

<script>
import { Plus, Close } from '@element-plus/icons-vue'
export default {
  props: {
    default: {
      type: Array,
      default: () => []
    },
    api: {
      type: String,
      default: ''
    },
    params: {
      type: Object,
      default: () => ({})
    },
    labelWidth: {
      type: [String, Number],
      default: '100'
    },
  },
  components: {
    Plus,
    Close
  },
  data() {
    return {
      formData: {},
      formItems: [],
      rules: [],
      operatorOptions: [
        {"text":"等于","value":"equal"},
        {"text":"等于其中之一","value":"one_of"},
        {"text":"不等于","value":"not_equal"},
        {"text":"大于","value":"greater_than"},
        {"text":"大于等于","value":"greater_than_equal"},
        {"text":"小于","value":"less_than"},
        {"text":"小于等于","value":"less_than_equal"},
        {"text":"属于范围","value":"between"},
        {"text":"不属于范围","value":"not_between"},
        {"text":"为空","value":"empty"},
        {"text":"不为空","value":"not_empty"},
        {"text":"包含","value":"contains"},
        {"text":"不包含","value":"not_contain"},
        {"text":"开头包含","value":"start_contain"},
        {"text":"开头不包含","value":"start_not_contain"},
        {"text":"结尾包含","value":"end_contain"},
        {"text":"结尾不包含","value":"end_not_contain"},
      ],
      loading: false,
      moreLoading: false,
      loadingKey: undefined
    };
  },
  watch: {
    api: {
      handler(val) {
        this.formItems = []
        const _this = this
        fetch(val).then((response) => {
          if (response.status === 200) {
            response.json().then((res) => {
              // this.formItems = res.slice(0, 1).map(el => {
              this.formItems = res.map(item => {
                item.supported_operator_options = item.supported_operator
                const defaultItem = this.default.find(i => i.field_key === item.field_key)
                if (item.field_component === 'select') {
                  this.getOptions(item).then(res => {
                    item.options = res
                  })
                }
                // console.log(defaultItem)
                if (defaultItem) {
                  item.supported_operator = defaultItem.supported_operator
                  item.moreOptions = defaultItem.moreOptions
                  item.more_condition = defaultItem.more_condition
                  item.more_field = defaultItem.more_field
                  item.value = defaultItem.value
                  if (defaultItem.supported_operator === 'more') {
                    this.getMoreOptions(item).then(res => {
                      item.moreOptions = res
                      item.more_condition.forEach(el => {
                        const o = item.moreOptions.find(o => o.field_key === el.field_key)
                        if (o) {
                          el.options = this.operatorOptions.filter(el => o.supported_operator.includes(el.value))
                        }
                      })
                    })
                  }
                } else {
                  item.supported_operator = ''
                  item.moreOptions = []
                  item.more_condition = []
                  item.more_field = {}
                  item.value = undefined
                  item.options = []
                  if (Object.keys(item.supported_operator_options).length === 1) {
                    console.log(Object.keys(item.supported_operator_options))
                    item.supported_operator = item.supported_operator_options[Object.keys(item.supported_operator_options)[0]]
                    this.onOperatorChange(item.supported_operator, item)
                  }
                }
                return item
              })
              this.initFormItems()
            })
          } else {
            console.error('请求失败')
          }
        })
      },
      immediate: true
    },
    formItems: {
      handler(val) {
        let data = JSON.parse(JSON.stringify(val))
        const invalid = data.some(this.check)
        // console.log(invalid)
        this.$emit('result', {
          data,
          valid: !invalid
        })
      },
      deep: true,
      immediate: true
    }
  },
  mounted() {
    this.$emit('loaded');
  },
  methods: {
    initFormItems () {
      this.rules = this.formItems.reduce((rules, item) => {
        if(item.is_require === 'yes') {
          rules[item.field_key] = {
            required: true,
          }
        }
        return rules;
      }, {})
    },
    async onOperatorChange (val, item) {
      console.log(val, item)
      if (val === 'more') {
        try {
          item.moreOptions = await this.getMoreOptions(item)
          if (item.more_condition.length === 0) {
            this.addCondition(item, -1)
          }
        } catch (error) {
          this.moreLoading = false
        }
      } else {
        item.more_condition = []
        if (val === 'one_of') {
          item.value = []
        } else if (val === 'between') {
          item.value = [undefined, undefined]
        } else if (val === 'auto') {
          item.value = 'auto'
        }
      }
    },
    getOptions (item) {
      const urlStr = Object.keys(this.params).map(key => `${encodeURIComponent(key)}=${encodeURIComponent(this.params[key])}`).join('&')
      return new Promise(async (resolve, reject) => {
        this.loading = true
        const response = await fetch(`${item.options_api}&${urlStr}`, {
          method: 'GET',
          headers: {
            'Content-Type': 'application/json'
          },
        })
        setTimeout(() => {
          this.loading = false
        }, 500)
        response.json().then(res => {
          resolve(Object.keys(res).map(key => ({value: res[key], text: key})))
          // if (res.code === 200) {
          //   resolve(res.data.rows)
          // } else {
          //   reject(new Error('more选项请求出错'))
          // }
        })
      })
    },
    getMoreOptions (item) {
      const urlStr = Object.keys(this.params).map(key => `${encodeURIComponent(key)}=${encodeURIComponent(this.params[key])}`).join('&')
      // console.log(urlStr)
      return new Promise(async (resolve, reject) => {
        this.moreLoading = true
        const response = await fetch(`${item.more_fields_api}&${urlStr}`, {
          method: 'GET',
          headers: {
            'Content-Type': 'application/json'
          },
        })
        setTimeout(() => {
          this.moreLoading = false
        }, 500)
        response.json().then(res => {
          if (res.code === 200) {
            resolve(res.data.rows)
          } else {
            reject(new Error('more选项请求出错'))
          }
        })
      })
    },
    check (m) {
      // 去掉不必要的属性
      Object.keys(m).forEach(key => {
        if (!['field_key', 'field_label', 'field_value_type', 'field_component', 'supported_operator', 'more_condition', 'value', 'is_require'].includes(key)) {
          delete m[key]
        }
      })
      if (m.is_require === 'no') return false
      if (m.is_require === 'yes') {
        if (m.supported_operator === 'more') {
          // console.log(m.more_condition)
          return m.more_condition.some(item => {
            delete item['options']
            switch (m['field_component']) {
              case 'input':
              case 'number':
              case 'select':
                // console.log(item)
                if (['between', 'not between'].includes(item.supported_operator)) {
                  return !item.field_value || item.field_value.some((v) => !v) || !item.value || !item.supported_operator || !item.field_key
                } else {
                  return !item.field_value || !item.value || !item.supported_operator || !item.field_key
                }
            }
          })
        } else if (m.supported_operator === 'one_of') {
          return m.value === undefined || m.value.length === 0
        } else {
          return m.value === undefined || !m.value
        }
      }
      delete m['is_require']
    },
    addCondition (item, index) {
      item.more_condition.splice(index + 1, 0, {
        field_id: Date.now(), // 因为可选择多个more选项，所以增加唯一标识字段
        field_label: undefined,
        field_key: undefined,
        field_value_type: undefined,
        field_component: undefined,
        supported_operator: undefined,
        field_value: undefined,
        value: undefined,
        pre_append_text: '',
        end_append_text: '',
      })
    },
    onMoreFieldChange (val, item, moreItem) {
      // console.log(val, item)
      const option = item.moreOptions.find(el => el.field_key === val)
      console.log(option)
      if (option) {
        moreItem.supported_operator = undefined
        moreItem.field_value = undefined
        moreItem.value = undefined
        moreItem.field_component = option.field_component
        moreItem.field_key = option.field_key
        moreItem.field_label = option.field_label
        moreItem.field_value_type = option.field_value_type
        moreItem.pre_append_text = option.pre_append_text
        moreItem.end_append_text = option.end_append_text
        moreItem.placeholder = option.placeholder
        moreItem.extra_config = option.extra_config
        if (option.field_component === 'select' && option.extra_config.options.length === 1) {
          moreItem.field_value = option.extra_config.options[0].value
        }
        // moreItem.more_field = option
        moreItem.options = this.operatorOptions.filter(el => option.supported_operator.includes(el.value))
      }
    },
    onMoreOperatorChange (val, moreItem) {
      console.log(val, moreItem)
      const option = moreItem.options.find(el => el.value === val)
      if (option) {
        if (['date', 'datetime', 'time', 'number'].includes(moreItem.field_component)) {
          moreItem.field_value = ['between', 'not between'].includes(val) ? [undefined, undefined] : undefined
        } else if (['input', 'select'].includes(moreItem.field_component)) {
          moreItem.field_value = ['one_of'].includes(val) ? [] : undefined
        }

      }
    }
  }
}
</script>

<style lang="scss" scoped>
:deep(.el-form-item__content) {
  align-items: flex-start;
}
:deep(.el-select) {
  display: block;
}
:deep(.el-input-number) {
  display: block;
  .el-input {
    display: block;
  }
}
:deep(.el-input__suffix-inner) {
  line-height: 30px;
}
:deep(.el-date-editor.el-input) {
  display: block;
}
.more {
  :deep(.el-form-item__content) {
    flex-direction: column;
  }
}
.more-condition {
  margin-top: 5px;
  padding: 8px 0px;
  margin-right: 10px;
  padding-right: 10px;
  border: 1px dashed #ccc; /* 设置虚线边框，颜色可以根据需要调整 */
  border-left: 0px dashed #ccc;
  border-radius: 3px;
  & > div {
    display: flex;
    align-items: flex-start;
    &:not(:first-child) {
      margin-top: 5px;
    }
  }
}
.invalid {
  &.group {
    border: 1px solid var(--el-color-danger);
  }
  :deep(.el-select__wrapper) {
    box-shadow: 0 0 0 1px var(--el-color-danger) inset;
  }
  :deep(.el-input__wrapper) {
    box-shadow: 0 0 0 1px var(--el-color-danger) inset;
  }
  :deep(.el-textarea__inner) {
    box-shadow: 0 0 0 1px var(--el-color-danger) inset;
  }
}
</style>